#ifndef _PACK_WRITER_H_
#define _PACK_WRITER_H_

#ifndef API
#include "net/net.h"
#endif

namespace pack {

class Writer {
	protected:
		net::IBuffer* buffer;

	public:
		Writer(net::IBuffer* buffer);
		~Writer();

	public:
		Writer& operator<<(uint32_t v);
		Writer& operator<<(std::string& v);

		Writer& operator<<(std::list<uint32_t>& v);
		Writer& operator<<(std::list<std::string>& v);

		template<typename T>
			Writer& operator<<(T& v);

		template<typename T>
			Writer& operator<<(std::list<T>& v);

		template<typename T>
			Writer& operator<<(std::vector<T>& v);

		template<typename T>
			Writer& operator<<(std::set<T>& v);

		template<typename T1, typename T2>
			Writer& operator<<(std::map<T1, T2>& v);
	};

	template<typename T>
		Writer& Writer::operator<<(T& v) {
			v.Serialize(buffer);
			return *this;
		}

	template<typename T>
		Writer& Writer::operator<<(std::list<T>& v) {
			size_t size = v.size();
			buffer->Write((char*)&size, sizeof(size_t));

			for(typename::std::list<T>::iterator it = v.begin(); it != v.end(); it++) {
				it->Serialize(buffer);
			}
			return *this;
		}

	template<typename T>
		Writer& Writer::operator<<(std::vector<T>& v) {
			size_t size = v.size();
			buffer->Write((char*)&size, sizeof(size_t));

			for(typename::std::vector<T>::iterator it = v.begin(); it != v.end(); it++) {
				this->operator<<(*it);
			}
			return *this;
		}

	template<typename T>
		Writer& Writer::operator<<(std::set<T>& v) {
			size_t size = v.size();
			buffer->Write((char*)&size, sizeof(size_t));

			for(typename::std::set<T>::iterator it = v.begin(); it != v.end(); it++) {
				this->operator<<(*it);
			}
			return *this;
		}

	template<typename T1, typename T2>
		Writer& Writer::operator<<(std::map<T1, T2>& v) {
			size_t size = v.size();
			buffer->Write((char*)&size, sizeof(size_t));

			for(typename::std::map<T1, T2>::iterator it = v.begin(); it != v.end(); it++) {
				this->operator<<(it->first)<<(it->second);
			}
			return *this;
		}

}
#endif
